<template>
    <van-uploader :fileList="fileList" :after-read="afterRead"
      multiple :max-count="maxCount" v-bind="$attrs" v-on="$listeners" />
  </template>
   
  <script>
  export default {
    name: 'compress-uploader',
    props: {
      value: Array,
      quality: {
        type: Number,
        default: 0.1
      },
      compressSwitch: {
        type: Boolean,
        default: false
      },
      threshold: {
        type: Number,
        default: 500
      },
      maxCount: {
        type: Number,
        default: 1
      }
    },
    computed: {
      fileList: {
        get () {
          return this.value
        },
        set (n) {
          this.$emit('input', n)
        }
      }
    },
    methods: {
      afterRead (file, detail) {
        console.log(file,'file')
        file.status = 'uploading'
        file.message = '上传中...'
        this.imgPreview(file, detail.index)
        console.log(file,'file')
        return true
      },
      // 处理图片
      async imgPreview (myFile, index) {
        const file = myFile.file
        if (!file || !window.FileReader) { // 看支持不支持FileReader
          return
        }
        const size = file.size / 1024
        console.log(`图片大小 ===> ${size}kb`)
        console.log('图片压缩：', this.compressSwitch ? '开' : '关')
        console.log('图片压缩阈值：', this.threshold + 'kb')
        console.log('图片压缩降帧值：', this.quality)
        if (/^image/.test(file.type) && size >= this.threshold && this.compressSwitch) {
          const img = new Image()
          img.src = await this.getBase64(file) // 将图片将转成base64格式
          img.onload = () => {
            const data = this.compress(img, file.name, file.type)
            console.log(`压缩后 ===> ${data.fileData.size / 1024}kb`)
            this.fileList[index] = {
              content: data.base64Data,
              file: data.fileData
            }
            console.log( this.fileList,' this.fileList')
            myFile.status = 'done'
          }
        } else {
          myFile.status = 'done'
        }
      },
      // 压缩图片
      compress (img, name, type) {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        // 瓦片canvas
        const tCanvas = document.createElement('canvas')
        const tctx = tCanvas.getContext('2d')
        let width = img.width
        let height = img.height
        // 如果图片大于四百万像素，计算压缩比并将大小压至400万以下
        let ratio
        if ((ratio = (width * height) / 4000000) > 1) {
          ratio = Math.sqrt(ratio)
          width /= ratio
          height /= ratio
        } else {
          ratio = 1
        }
        canvas.width = width
        canvas.height = height
        // 铺底色
        ctx.fillStyle = '#fff'
        ctx.fillRect(0, 0, canvas.width, canvas.height)
        // 如果图片像素大于100万则使用瓦片绘制
        let count
        if ((count = (width * height) / 1000000) > 1) {
          count = ~~(Math.sqrt(count) + 1) // 计算要分成多少块瓦片
          // 计算每块瓦片的宽和高
          const nw = ~~(width / count)
          const nh = ~~(height / count)
          tCanvas.width = nw
          tCanvas.height = nh
          for (let i = 0; i < count; i++) {
            for (let j = 0; j < count; j++) {
              tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh)
              ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)
            }
          }
        } else {
          ctx.drawImage(img, 0, 0, width, height)
        }
        // 进行压缩
        const ndata = canvas.toDataURL('image/jpeg', this.quality)
        tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0
        return { base64Data: ndata, fileData: this.dataURLtoFile(ndata, name, type) }
      },
      // 获取图片base64格式
      getBase64 (data) {
        return new Promise((resolve, reject) => {
          const fileReader = new FileReader()
          fileReader.onload = (e) => {
            resolve(e.target.result)
          }
          fileReader.readAsDataURL(data)
          fileReader.onerror = () => {
            reject(new Error('文件流异常'))
          }
        })
      },
      // 将base64转换为文件
      dataURLtoFile (dataurl, name, type) {
        name = name || '图片'
        type = type || 'jpg'
        const arr = dataurl.split(',')
        const bstr = atob(arr[1])
        let n = bstr.length
        const u8arr = new Uint8Array(n)
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n)
        }
        return new File([u8arr], name, {
          type: type
        })
      }
    }
  }
  </script>